﻿using Devil;
using System.Collections;
using System.Reflection;
using UnityEditor.Experimental.GraphView;
using UnityEngine;

namespace GameToolkit.Editor
{
    public class StoryNodeLib : SearchTreeLib<StoryNodeLib>
    {
        public static FilterDelegate<SearchTreeEntry> NO_FILTER = (entry) => true;

        [InitializeOnLoadMethodParallel(IsOnMainThread = true)]
        static IEnumerator Init()
        {
            yield return LoadLib();
        }

        public override string SearchTreeTitle => "Story Graph Nodes";

        public override string Icon => "69d707018c2bd2b40847fe77dc8d1b1b";

        public override bool IsNodeType(System.Type nodeType)
        {
            var isStoryNode = GlobalUtil.IsTypeInheritedFrom(nodeType, typeof(TaskGraphAsset.NodeAsset));
            return isStoryNode;
        }

        protected override NodeInfo CreateNodeInfo(JsonSerializedObject.TypeWrapper wrapper)
        {
            return new StoryNodeInfo(wrapper);
        }

        public class StoryNodeInfo : NodeInfo
        {
            TaskResultAttribute[] mResults;
            public bool IsHiddenGiveUp { get; private set; }
            public bool IsReservedAlways { get; private set; }
            public bool IsReservedGiveUp { get; private set; }
            public bool IsReservedFinish { get; private set; }
            public TaskResultAttribute[] Results => mResults;

            public StoryNodeInfo(JsonSerializedObject.TypeWrapper wrapper) : base(wrapper)
            {
                var lst = CachedList<TaskResultAttribute>.GetList();
                var att = wrapper.WrapType.GetCustomAttributes<TaskResultAttribute>();
                if(att != null)
                {
                    foreach(var item in att)
                    {
                        //if(item.Value == TaskNode.RESULT_KILLED || item.Value == TaskNode.RESULT_FINISH)
                        //{
                        //    var kind = item.Value == TaskNode.RESULT_FINISH ? "any result" : "killed result";
                        //    Debug.LogError($"The task result({item.Value}) is reserved for {kind}, don't use it as result code.(class: {wrapper.Name})");
                        //    continue;
                        //}
                        bool exist = false;
                        for (int i = 0; !exist && i < lst.Count; i++)
                        {
                            exist = lst[i].Value == item.Value;
                        }
                        if (exist)
                        {
                            Debug.LogError($"The task result({item.Value}) is defined serveral times.(class: {wrapper.Name})");
                            continue;
                        }
                        lst.Add(item);
                        if (string.IsNullOrEmpty(item.PortName))
                            item.PortName = $"#{item.Value}";
                        if (item.PortColor == default)
                            item.PortColor = Color.gray;
                        if (item.Value == (int)EReservedTaskResult.Always)
                            IsReservedAlways = true;
                        else if (item.Value == (int)EReservedTaskResult.Finish)
                            IsReservedFinish = true;
                        else if (item.Value == (int)EReservedTaskResult.GiveUp)
                            IsReservedGiveUp = true;
                    }
                }
                var hidden = wrapper.WrapType.GetCustomAttribute<HideTaskNodePortAttribute>();
                if (hidden != null)
                {
                    IsReservedAlways |= hidden.HideAlways;
                    IsReservedFinish |= hidden.HideFinish;
                    IsReservedGiveUp |= hidden.HideGiveUp;
                    IsHiddenGiveUp |= hidden.HideGiveUpInput;
                }
                mResults = lst.ToArray();
                CachedList<TaskResultAttribute>.Release(lst);
            }
        }
    }
}
